package com.ciaojian.miniapp.model.request.submessage;


import com.ciaojian.miniapp.model.request.BaseRequest;
import lombok.var;
import org.apache.commons.lang3.ObjectUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 消息推送基础模板
 *
 * @author Atlakyn
 */
public class BaseTemplate extends BaseRequest {

    /**
     * 接收者（用户）的 openid
     */
    private String touser;

    /**
     * 所需下发的订阅模板id
     */
    private String template_id;

    /**
     * 点击模板卡片后的跳转页面，仅限本小程序内的页面。支持带参数,（示例index?foo=bar）。该字段不填则模板无跳转
     */
    private String page;

    /**
     * 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }
     */
    private BaseDataTemplate data;

    /**
     * 跳转小程序类型：
     * developer 为开发版；
     * trial 为体验版；
     * formal 为正式版；默认为正式版
     */
    private String miniprogram_state;

    /**
     * 进入小程序查看”的语言类型，支持
     * zh_CN(简体中文)，默认
     * en_US(英文)
     * zh_HK(繁体中文)
     * zh_TW(繁体中文)
     */
    private String lang;

    /**
     * 将建构的 builder 转为 Map
     *
     * @return 转化后的 Map
     */
    public String toJsonStr() {
        // 获取对象全部属性
        String[] fieldNames = getFieldNames(this);
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        // 遍历属性，取出值放入 map
        for (int i = 0, l = fieldNames.length; i < l; i++) {
            String fieldName = fieldNames[i];
            // 根据属性名取值
            Object value = getFieldValueByName(fieldName, this);
            // 值为空进入下一次循环
            if (value == null) {
                continue;
            }
            sb.append(String.format("\"%s\": ", fieldName));
            // 如果对象的属性是 BaseTemplate 类型
            if (value instanceof BaseDataTemplate) {
                sb.append("{");
                // 获取 BaseDataTemplate 属性名数组
                var f = getFieldNames(value);
                // 遍历 BaseTemplate 类型的属性转成微信要求的格式的字符串
                for (int j = 0, length = f.length; j < length; j++) {
                    String fName = f[j];
                    if (j < length - 1) {
                        sb.append(String.format("\"%s\": {\"value\":\"%s\"},", fName, getFieldValueByName(fName, value)));
                    } else {
                        sb.append(String.format("\"%s\": {\"value\":\"%s\"}", fName, getFieldValueByName(fName, value)));
                    }
                }
                sb.append("}");
            } else if (ObjectUtils.isNotEmpty(value)) {
                sb.append(String.format("\"%s\"", value));
                // 非最后一个字符加上 , 号
                if (i < l - 1) {
                    sb.append(",");
                }
            }
        }
        sb.append("}");
        System.err.println(sb);
        return sb.toString();
    }

    /**
     * 获取属性名数组
     *
     * @param obj 对象
     * @return 返回对象属性名数组
     */
    private String[] getFieldNames(Object obj) {
        Field[] fields = obj.getClass().getDeclaredFields();
        String[] fieldNames = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            fieldNames[i] = fields[i].getName();
        }
        return fieldNames;
    }

    /**
     * 根据属性名获取属性值
     *
     * @param fieldName 属性名称
     * @param obj       对象
     * @return 返回对应属性的值
     */
    private Object getFieldValueByName(String fieldName, Object obj) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = new StringBuffer().append("get")
                    .append(firstLetter)
                    .append(fieldName.substring(1))
                    .toString();
            Method method = obj.getClass().getMethod(getter);
            return method.invoke(obj);
        } catch (Exception e) {
            return null;
        }
    }

    public static BaseTemplate builder(TemplateIdEnum templateIdEnum) {
        BaseTemplate baseTemplate = new BaseTemplate();
        baseTemplate.setTemplate_id(templateIdEnum.getId());
        baseTemplate.setPage(templateIdEnum.getPage());
        return baseTemplate;
    }

    public BaseTemplate touser(String touser) {
        this.touser = touser;
        return this;
    }

    public BaseTemplate data(BaseDataTemplate data) {
        this.data = data;
        return this;
    }

    public BaseTemplate miniprogramState(String miniprogramState) {
        this.miniprogram_state = miniprogramState;
        return this;
    }

    public BaseTemplate lang(String lang) {
        this.lang = lang;
        return this;
    }

    public String getTouser() {
        return touser;
    }

    public void setTouser(String touser) {
        this.touser = touser;
    }

    public String getTemplate_id() {
        return template_id;
    }

    public void setTemplate_id(String template_id) {
        this.template_id = template_id;
    }

    public String getPage() {
        return page;
    }

    public void setPage(String page) {
        this.page = page;
    }

    public BaseDataTemplate getData() {
        return data;
    }

    public void setData(BaseDataTemplate data) {
        this.data = data;
    }

    public String getMiniprogram_state() {
        return miniprogram_state;
    }

    public void setMiniprogram_state(String miniprogram_state) {
        this.miniprogram_state = miniprogram_state;
    }

    public String getLang() {
        return lang;
    }

    public void setLang(String lang) {
        this.lang = lang;
    }
}